using System;
using System.Collections.Generic;
using Moq;
using NUnit.Framework;
using Microsoft.Build.Framework;
using System.Management.Automation;
using System.Management.Automation.Host;

namespace Fines.Powershell.PowershellMSBuildTask.Tests
{
    [TestFixture]
    public class PowershellHostUITest
    {
        private Mock<IPowershellTask> powershellTaskMock;
        private BuildEngineMock buildEngineMock;

        private PowershellHostUI ui;

        [SetUp]
        public void SetUp()
        {
            this.buildEngineMock = new BuildEngineMock();

            this.powershellTaskMock = new Mock<IPowershellTask>();
            this.powershellTaskMock.SetupGet( t => t.BuildEngine).Returns( this.buildEngineMock );

            this.ui = new PowershellHostUI( this.powershellTaskMock.Object );
        }

        [TearDown]
        public void TearDown()
        {
        }

        [Test]
        public void WriteLine()
        {
            this.ui.WriteLine("Hello world");

            Assert.AreEqual( "Hello world", this.buildEngineMock.MessageBuildEvents[ 0 ].Message );
            Assert.AreEqual( MessageImportance.High, this.buildEngineMock.MessageBuildEvents[ 0 ].Importance );
        }

        [Test]
        public void Write()
        {
            this.ui.Write( "Hullo world" );
            Assert.AreEqual( "Hullo world", this.buildEngineMock.MessageBuildEvents[ 0 ].Message );
            Assert.AreEqual( MessageImportance.High, this.buildEngineMock.MessageBuildEvents[ 0 ].Importance );
        }

        [Test]
        public void WriteColor()
        {
            this.ui.Write( ConsoleColor.Blue, ConsoleColor.Black, "Hello color" );
            Assert.AreEqual( "Hello color", this.buildEngineMock.MessageBuildEvents[ 0 ].Message );
            Assert.AreEqual( MessageImportance.High, this.buildEngineMock.MessageBuildEvents[ 0 ].Importance );
        }

        [Test]
        public void WriteDebugLine()
        {
            this.ui.WriteDebugLine( "Hello debug" );
            Assert.AreEqual( "Hello debug", this.buildEngineMock.MessageBuildEvents[ 0 ].Message );
            Assert.AreEqual( MessageImportance.Low, this.buildEngineMock.MessageBuildEvents[ 0 ].Importance );
        }

        [Test]
        public void WriteWarningLine()
        {
            this.ui.WriteWarningLine( "Hello warning" );
            Assert.AreEqual( "Hello warning", this.buildEngineMock.WarningBuildEvents[ 0 ].Message );
        }

        [Test]
        public void WriteErrorLine()
        {
            this.ui.WriteErrorLine( "Hello error" );
            Assert.AreEqual( "Hello error", this.buildEngineMock.ErrorBuildEvents[ 0 ].Message );
        }

        [Test]
        public void WriteVerboseLine()
        {
            this.ui.WriteVerboseLine( "Hello verbose" );
            Assert.AreEqual( "Hello verbose", this.buildEngineMock.MessageBuildEvents[ 0 ].Message );
        }

        [Test]
        [ExpectedException(typeof(NotImplementedException))]
        public void Prompt()
        {
            this.ui.Prompt( null, null, null );
        }

        [Test]
        [ExpectedException( typeof( NotImplementedException ) )]
        public void PromptForChoice()
        {
            this.ui.PromptForChoice( null, null, null, 0 );
        }

        [Test]
        [ExpectedException( typeof( NotImplementedException ) )]
        public void PromptForCredential()
        {
            this.ui.PromptForCredential( null, null, null,null, PSCredentialTypes.Generic, PSCredentialUIOptions.None );
        }

        [Test]
        [ExpectedException( typeof( NotImplementedException ) )]
        public void PromptForCredential2()
        {
            this.ui.PromptForCredential( null, null, null, null );
        }

        [Test]
        [ExpectedException( typeof( NotImplementedException ) )]
        public void ReadLine()
        {
            this.ui.ReadLine();
        }

        [Test]
        [ExpectedException( typeof( NotImplementedException ) )]
        public void ReadLineAsSecureString()
        {
            this.ui.ReadLineAsSecureString();
        }

        [Test]
        public void RawUI()
        {
            PSHostRawUserInterface pi = this.ui.RawUI;
            Assert.IsNotNull( pi );
        }

        [Test]
        public void WriteProgress()
        {
            this.ui.WriteProgress( 0, new ProgressRecord( 0, "Hi", "Ho" ) );
        }



        

        private class BuildEngineMock : IBuildEngine
        {
            private readonly List<CustomBuildEventArgs> CustomBuildEvents = new List<CustomBuildEventArgs>();
            public readonly List<BuildErrorEventArgs> ErrorBuildEvents = new List<BuildErrorEventArgs>();
            public readonly List<BuildMessageEventArgs> MessageBuildEvents = new List<BuildMessageEventArgs>();
            public readonly List<BuildWarningEventArgs> WarningBuildEvents = new List<BuildWarningEventArgs>();
            
            #region IBuildEngine Members

            public bool BuildProjectFile( string projectFileName, string[] targetNames, System.Collections.IDictionary globalProperties, System.Collections.IDictionary targetOutputs )
            {
                throw new Exception( "The method or operation is not implemented." );
            }

            public int ColumnNumberOfTaskNode
            {
                get { throw new Exception( "The method or operation is not implemented." ); }
            }

            public bool ContinueOnError
            {
                get { return true; }
            }

            public int LineNumberOfTaskNode
            {
                get { throw new Exception( "The method or operation is not implemented." ); }
            }

            public void LogCustomEvent( CustomBuildEventArgs e )
            {
                this.CustomBuildEvents.Add( e );
            }

            public void LogErrorEvent( BuildErrorEventArgs e )
            {
                this.ErrorBuildEvents.Add( e );
            }

            public void LogMessageEvent( BuildMessageEventArgs e )
            {
                this.MessageBuildEvents.Add( e );
            }

            public void LogWarningEvent( BuildWarningEventArgs e )
            {
                this.WarningBuildEvents.Add( e );
            }

            public string ProjectFileOfTaskNode
            {
                get { return ""; }
            }

            #endregion
        }
}
}
